package com.codes.core.utils.word;

import com.codes.core.utils.snowflake.SnowUtil;
import com.deepoove.poi.XWPFTemplate;
import com.documents4j.api.DocumentType;
import com.documents4j.api.IConverter;
import com.documents4j.job.LocalConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Map;


/** **
 * @param
 * @Description   word文件的 操作工具类
 * @return
 * @Date 2020/6/28 20:51
 * @Created by peanut
 */
@Slf4j
public class WordUtils {

    @Value("${file-save-temp-path}")
    private   String fileSaveTempPath;
    // 注入静态变量 word文件生成的   路径  -- 可以 返回 前台 URL  也可以返回文件流
    private static String fileTemp;

    @PostConstruct
    public void init(){
        fileTemp = fileSaveTempPath;
    }

    /**
     *
     * @param tplUrl  word模板文件 路径
     * @param tplName   模板文件名称
     * @param mapParam  渲染到模板的数据
     * @return          返回渲染后的word
     * @throws IOException
     */
    public static File getWordDoc(String tplUrl, String tplName, Map<String,Object> mapParam) throws IOException {
        File file=new File(fileTemp);
        if(!file.exists()){//如果文件夹不存在s
            file.mkdirs();//创建文件夹
        }
        String reUrl = getFileTempUrl(1);// docx
        File re = new File(reUrl);
        ClassPathResource resource = new ClassPathResource(tplUrl + tplName); // 此方式   打 jar 运行也可以 找到模板
       /* File sourceFile = resource.getFile();
        String sourceFilePath = sourceFile.getPath();
        String tplPath =  PoiTlUtils.class.getResource(tplUrl).getPath();
*/
        //tplUrl = PoiTlUtils.class.getResource(tplUrl).getPath() + tplName;
        //  tplUrl = sourceFilePath + tplName;
        log.info("word模板路径:{}",tplUrl);
        log.info("自动生成word文件路径:{}",reUrl);
      /*  XWPFTemplate template = XWPFTemplate.compile(tplUrl)    // 模板路径  项目打成jar包 获取不到文件. 只能通过文件流 获取模板文件
                .render(mapParam);// 渲染参数*/
        XWPFTemplate template = XWPFTemplate.compile(resource.getInputStream())    // 模板文件流
                .render(mapParam);// 渲染参数
        FileOutputStream out = new FileOutputStream(reUrl);
        template.write(out);
        out.flush();
        out.close();
        template.close();
        return re;
    }

    /****
     * @param fileType 1 docx  2 pdf
     * @return java.lang.String 文件路径及名称
     * @Date 2020/7/7 18:00
     * @Created by peanut
     */
    public static String getFileTempUrl(int fileType){
        File file=new File(fileTemp);
        if(!file.exists()){//如果文件夹不存在
            file.mkdirs();//创建文件夹
        }
        String type = ".docx";
        if (1 == fileType)    type = ".docx";
        if (2 == fileType)    type = ".pdf";
        String fileName = SnowUtil.getOne().nextId() + ""; // 雪花 id 生成文件名
        // 文件生成的路径
        return fileTemp + fileName + type;
    }

    /****
     * @param response
     * @param file  返回到前台相应的 文件
     * @Description   文件流返回到前台
     * @return void
     * @Date 2020/6/28 20:51
     * @Created by peanut
     */
    public static void fileToResponse( HttpServletResponse response, File file){
        BufferedInputStream bis = null;
        OutputStream toClient =null;
        try {
            bis = new BufferedInputStream(new FileInputStream(file), 1024);
            toClient = new BufferedOutputStream(response.getOutputStream());
            response.reset();
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);

            //  跨域
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Accept-Ranges", "bytes"); // 服务器可以接受范围请求
            //需要使用请求头Access-Control-Expose-Headers进行说明 防止页面js 报跨域异常
            response.addHeader("Access-Control-Expose-Headers", "Accept-Ranges,Content-Encoding");
            response.setHeader("Access-Control-Allow-Headers", "Content-Type, Content-Length, Authorization, Accept, X-Requested-With, Current-Page,Accept-Ranges");

            response.setHeader("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS");
            //获取oss端文件的文件名，用作于下载文件的名称
            response.setContentType("application/octet-stream");
            //处理文件名为中文的情况
            response.setHeader("Content-Disposition", "attach;filename=" + new String(file.getName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
            //*处理oss文件流传输*
            int number;
            byte[] buffer = new byte[1024];
            while ((number = bis.read(buffer)) != -1) {
                toClient.write(buffer, 0, number);
            }
            bis.close();
            toClient.flush();
            toClient.close();
            log.info("返回文件流到前台");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {

        }

    }

    /****
     * @param docFile  doc 文件
     * @Description   doc  转 pdf
     *      com.documents4j.api.IConverter;
     * @return   pdf 文件
     * @Date 2020/6/28 20:48
     * @Created by peanut
     */
    public static File docToPdf(File docFile) throws FileNotFoundException {

        String pdfName = getFileTempUrl(2);//pdf
        File outputFile = new File(pdfName);

        try (   // 用完 关闭流
                InputStream docxInputStream = new FileInputStream(docFile);
                OutputStream outputStream = new FileOutputStream(outputFile);

                ){
            IConverter converter = LocalConverter.builder().build();
            converter.convert(docxInputStream).as(DocumentType.DOCX).to(outputStream).as(DocumentType.PDF).execute();
            //      docxInputStream.close();
            outputStream.close();
            log.info("{} 文件转换为 {}",docFile.getName(),outputFile.getName());
            docFile.delete();
            log.info("{} 文件转换PDF完毕,删除文件docx  ",docFile.getName() );
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            // if (null != docx)
        }
        return outputFile;
    }

    // end
}